

let path = require('path')
const ESLintPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
const { extendDefaultPlugins } = require('svgo');
const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin');
const WorkboxPlugin = require('workbox-webpack-plugin')
const os = require('os');
const threads = os.cpus().length  - 1;
//封装处理样式的loader
function getStyleLoader(pre){
  return [
    MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  [
                    'postcss-preset-env',
                  ],
                ],
              },
            },
          },
          ...pre
    ].filter(Boolean); //从右往左执行
}
module.exports = {
  entry:path.join(__dirname, '/src/index.js'),
  // entry:{
  //   index:path.join(__dirname, '/src/index.js'),
  //   app:path.join(__dirname, '/src/app.js')
  // } ,  //输入文件
  output: {
		path: path.join(__dirname, 'dist'),
		publicPath: '/dist/',  //输出路径
		filename: 'static/js/[name].[contenthash:8].js', //输出文件,放在static/js文件夹，将js的文件放在这里
    clean:true,//清除上次打包的内容
    //给打包输出的其他文件进行命名
    chunkFilename:'static/js/[name][contenthash:8].chunk.js', //加入chunk区分主文件
    //通过type:asset处理的资源
    assetModuleFilename:'static/assets/[hash:10][ext][query]'
	},
  //配置loader
  module:{
    //loader配置再rules里面 
    rules:[
      {
        oneOf:[
          //处理css文件
          {
            test:/\.css$/,
            use:getStyleLoader([])
          },
          //处理less文件
          {
            test:/\.less$/,
            use:getStyleLoader(['less-loader'])
          },
          //处理sass,scss文件
          {
            test:/\.s[ac]ss$/,
            use:getStyleLoader(['sass-loader'])
          },
          //被指bable,处理js文件，能够兼容更加高级的js，es6....等，还有core.js,让你能使用基于 JavaScript 进行了拓展的语言，比如 React 的 JSX
            {
              test: /\.js$/,
              exclude: /node_modules/,//不处理node_modules文件
              use: [
                {
                loader: 'babel-loader',
                options: {
                  // presets: ['@babel/preset-env'],//可以在babel.config.js
                  plugins: ['@babel/plugin-transform-runtime'],
                  cacheDirectory:true, //开启bable缓存
                  cacheCompression:false,//关闭缓存压缩
                },
              },
               // 开启多进程
              {
                loader: 'thread-loader',
                options: {
                  works:threads
                },
              },
            ]
            },
          //处理图片资源，，webpack 将按照默认条件，自动地在 resource 和 inline 之间进行选择：小于 8kb 的文件，将会视为 inline 模块类型，否则会被视为 resource 模块类型，
          //有三种类型选择 asset,asset/resource,asset/inline
          // asset就是就是会在尺寸(默认8kb)是多少会进行base64转换，直接URL进行注入
          //asset/resource 进行就是单独一个文件，asset/inline 是转换为base64,可以减少请求
          {
            test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
            type:'asset',
            //生成的结果
            generator:{
              //hash是生成的hash值，hash:10 取前十位
              //ext 是指后缀
              //query 是携带的参数
            // filename:"static/assets/[hash:10][ext][query]"
            },
            parser: {
              dataUrlCondition: {
                maxSize: 10 * 1024 // 4kb
              }
            }
          },
          //处理字体文件
          {
            test: /\.(tff|woff2)(\?.*)?$/,
            type:'asset/resource',//不需要转成base64
            //生成的结果
            generator:{
              //hash是生成的hash值，hash:10 取前十位
              //ext 是指后缀
              //query 是携带的参数
            // filename:"static/assets/[hash:10][ext][query]"
            }
          }
        ]
      }
    ]
  },
  //配置插件
  plugins:[
    // 安装eslint插件,配置.eslintrc文件
    new ESLintPlugin({
      context:path.resolve(__dirname,"src"),
      exclude:'node_modules',
      cache:true, //开启缓存
      cacheLocation:path.resolve(__dirname,"../node_module/.cache/eslintcache"), //配置缓存的位置
      threads:threads //开启多进程
    }),
    new HtmlWebpackPlugin({
      //以public下的index.html为模板，将输出的资源加上去，其他的不变
      template:path.resolve(__dirname,"public/index.html")
    }),
    //提取css文件
    new MiniCssExtractPlugin({
      filename:'static/css/[name].css',
      chunkFilename:'static/css/[name].chunk.css'
    }),
    new CssMinimizerPlugin(),
    new PreloadWebpackPlugin({
      // rel: 'preload', //设置加载的方式
      // as: 'script' //处理的优先级
      rel:'prefetch'
    }),
    new WorkboxPlugin.GenerateSW({
      // 这些选项帮助快速启用 ServiceWorkers
      // 不允许遗留任何“旧的” ServiceWorkers
      clientsClaim: true,
      skipWaiting: true,
    })
  ],
  optimization: {
      splitChunks: {
        chunks: 'all',
        //默认值
        // minSize: 20000,//分割代码的最小的大小
        // minRemainingSize: 0,
        // minChunks: 1,//至少使用的次数
        // maxAsyncRequests: 30,//同时加载的次数
        // maxInitialRequests: 30,
        // enforceSizeThreshold: 50000,//超过50kb就单独打包
        // cacheGroups: {//组，哪些文件打包在一起
        //   defaultVendors: {
        //     test: /[\\/]node_modules[\\/]/,
        //     priority: -10,
        //     reuseExistingChunk: true,
        //   },
        //   default: {
        //     minChunks: 2,
        //     priority: -20,
        //     reuseExistingChunk: true,
        //   },
        // },
        cacheGroups: {
          // defaultVendors: {
          //   test: /[\\/]node_modules[\\/]/,
          //   priority: -10,
          //   reuseExistingChunk: true,
          // },//组，哪些文件打包在一起
          default: {
            minSize:0,//打包的最小的体积
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true,
          },
        },
      },
    minimizer: [
      // 在 webpack@5 中，你可以使用 `...` 语法来扩展现有的 minimizer（即 `terser-webpack-plugin`），将下一行取消注释
      // `...`,
      new CssMinimizerPlugin(),
      // new ImageMinimizerPlugin({
      //   minimizerOptions: {
      //     implementation:ImageMinimizerPlugin.imageminGenerate,
      //     plugins: [
      //       ['gifsicle', { interlaced: true }],
      //       ['jpegtran', { progressive: true }],
      //       ['optipng', { optimizationLevel: 5 }],
      //       // Svgo configuration here https://github.com/svg/svgo#configuration
      //       [
      //         'svgo',
      //         {
      //           plugins: extendDefaultPlugins([
      //             {
      //               name: 'removeViewBox',
      //               active: false,
      //             },
      //             {
      //               name: 'addAttributesToSVGElement',
      //               params: {
      //                 attributes: [{ xmlns: 'http://www.w3.org/2000/svg' }],
      //               },
      //             },
      //           ]),
      //         },
      //       ],
      //     ],
      //   },
      // }),
    ],
    minimize: true,
      // 提取runtime文件
    runtimeChunk: {
      name: (entrypoint) => `runtime~${entrypoint.name}`, // runtime文件命名规则
    },
  },
  devServer: {
        static: {
            directory: path.join(__dirname, '/dist/'),
        },
        compress: true,
        port: '8088', // 设置端口号为8088
        historyApiFallback: true, //不跳转
        hot:true
  },
  mode:'development',
  devtool:'cheap-module-source-map'
}